﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TheHeGeoDao;

namespace TheHeGeoDataProcess
{
    public class DataProcess
    {
        public static EquipmentData DataFromStr(string input)
        {
            return new EquipmentData(input);
        }
    }

    public class Sensor
    {
        public string Id { get; set; }
        public DateTime LogTime { get; set; }
        public double Value { get; set; }
        public string MaSensorDb { get; set; }
        public string CongThuc { get; set; }
        public int MaDuAn { get; set; }
        public int DbId { get; set; }
    }

    public class EquipmentData
    {
        public const string BLOCK_SPLITER = ";";
        public const string DATA_SPLITER = "---";
        public EquipmentData(string str)
        {
            SensorDict=new Dictionary<string, Sensor>();
            RawData = str;
        }

        protected string PrtRawData ;
        public string RawData {
            get { return PrtRawData; }
            set
            {
                DecodeRawData(value);
            }
        }
        public string Cmd { get; set; }

        public string ErrStr { get; set; }
        public string ErrCode { get; protected set; }
        public bool IsCorrect { get; protected set; }
        public string Header { get; set; }
        public string UserId { get; set; }
        public string DeviceId { get; set; }
        public string DeviceDesc { get; set; }
        public int DataLength { get; set; }
        public int SensorInput { get; set; }
        public Dictionary<string, Sensor> SensorDict { get; set; }
        public string Status { get; set; }
        public string Reserve { get; set; }
        public string Crc { get; set; }
        public string Footer { get; set; }

        public static string ReFormatStr(string input)
        {
            int index = 0;
            string result = input.Substring(index, 4);
            index += 4;
            result += AddBlock(input.Substring(index, 4));
            index += 4;
            result += AddBlock(input.Substring(index, 6));
            index += 6;
            result += AddBlock(input.Substring(index, 6));
            index += 6;
            result += AddBlock(Environment.NewLine);

            result += input.Substring(index, 2);
            var sensorInput = Convert.ToInt32(input.Substring(index, 2));
            index += 2;
            result += AddBlock(input.Substring(index, 2));
            var dataLength = Convert.ToInt32(input.Substring(index, 2));
            index += 2;
            for (int i = 0; i < dataLength; i++)
            {
                result += (Environment.NewLine + DATA_SPLITER+Environment.NewLine);
                string date = input.Substring(index, 6);
                index += date.Length;

                string time = input.Substring(index, 8);
                index += time.Length;

                result += (date + time);

                for (int j = 0; j < sensorInput; j++)
                {
                    result += AddBlock(input.Substring(index, 8));
                    index += 8;
                }
                result += (Environment.NewLine + DATA_SPLITER + Environment.NewLine);
            }

            int backIndex = input.Length;
            backIndex -= 4;
            string backRs = (input.Substring(backIndex, 4));
            backIndex -= 2;
            backRs += AddBlock(input.Substring(backIndex, 2));
            backIndex -= 16;
            backRs += AddBlock(input.Substring(backIndex, 16));
            backIndex -= 4;
            backRs += AddBlock(input.Substring(backIndex, 4));

            return result + backRs;

        }

        protected static string AddBlock(string str)
        {
            return BLOCK_SPLITER + str;
        }

        public virtual void DecodeRawData(string raw)
        {
            try
            {
                PrtRawData = raw;
                IsCorrect = true;
                int index = 0;
                Header = raw.Substring(index, 4);
                index += Header.Length;
                UserId = raw.Substring(index, 4);
                index += UserId.Length;
                DeviceId += raw.Substring(index, 6);
                index += DeviceId.Length;
                DeviceDesc = raw.Substring(index, 6);
                index += DeviceDesc.Length;

                SensorInput = Convert.ToInt32(raw.Substring(index, 2));
                index += 2;
                DataLength = Convert.ToInt32(raw.Substring(index, 2));
                index += 2;

                int backIndex = raw.Length;
                backIndex -= 4;
                Footer = raw.Substring(backIndex, 4);
                backIndex -= 2;
                Crc = raw.Substring(backIndex, 2);
                backIndex -= 16;
                Reserve = raw.Substring(backIndex, 16);
                backIndex -= 4;
                Status = raw.Substring(backIndex, 4);

                //int numOfSensor = (((backIndex - index)/DataLength) - 8 - 6)/8;
                
                for (int i = 0; i < DataLength; i++)
                {
                    string date = raw.Substring(index , 6);
                    index += date.Length;
                    
                    DateTime tempDate;
                    if (!DateTime.TryParseExact("20"+date, "yyyyMMdd", CultureInfo.CurrentCulture, 
                        DateTimeStyles.None,out tempDate))
                    {
                        IsCorrect = false;
                        ErrCode = "02";
                        ErrStr = "Date invalid at index: " + index + " value:" + date;
                        return;
                    }

                    string time = raw.Substring(index, 8);
                    index += time.Length;
                    tempDate = tempDate.AddHours(Convert.ToDouble(time.Substring(0, 2)));
                    tempDate = tempDate.AddMinutes(Convert.ToDouble(time.Substring(2, 2)));
                    tempDate = tempDate.AddSeconds(Convert.ToDouble(time.Substring(4, 2)));
                    tempDate = tempDate.AddMilliseconds(Convert.ToDouble(time.Substring(6, 2))*10);

                    double h = (tempDate - DateTime.Now).TotalDays;
                    if (h > 1 || h < -7)
                    {
                        IsCorrect = false;
                        ErrCode = "02";
                        ErrStr = "Date invalid at index: " + index + " value:" + date;
                        return;
                    }
                    double s = (tempDate - DateTime.Now).TotalSeconds;
                    if (s > 10 || s < -300) //nếu lệch 10 giay
                    {
                        ErrCode = "9999"; 
                    }
                    for (int j = 0; j < SensorInput; j++)
                    {
                        var sensor = new Sensor
                        {
                            LogTime = tempDate,
                            Id = i + "_" + j,
                            Value = Convert.ToDouble(raw.Substring(index, 8))
                        };
                        index += 8;
                        SensorDict.Add(sensor.Id,sensor);
                    }
                }
               
            }
            catch (Exception ex)
            {
                IsCorrect = false;
                ErrCode = "00";
                ErrStr = ex.StackTrace;
            }
        }


    }
}
